package miningMinds;

import java.io.File;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import parameter.*;
import modules.*;
import jxl.Workbook;
import jxl.write.*;
import jxl.write.biff.RowsExceededException;

public class MiningMindsMain {

	static int exp_ct = 0;
	static int total_exp_ct = 0;
	static WritableWorkbook workbook;
	static WritableSheet sheet; // for cosine similarity
	static WritableSheet sheet2; // for short text classification accuracy
	
	static int col;
	static WritableCellFormat cellFormat;
	static WritableFont cellFont;

	public static void init() throws Exception{
		File dir = new File(Path.RESULT_PATH, Exp.resultPathAppend);
		if(!dir.exists()) dir.mkdir();
		workbook = Workbook.createWorkbook(new File( dir.getCanonicalPath() + "\\result_"+Exp.resultPathAppend+".xls"));
		sheet = workbook.createSheet("sheet 0",  0);
		sheet2 = workbook.createSheet("sheet 1",  1);
		
	    cellFont = new WritableFont(WritableFont.TAHOMA, 12);
	    cellFormat = new WritableCellFormat(cellFont);
	}
	
	public static void main(String args[]) throws Exception{
		System.out.println("Start");
		init();
		//--------------Exp Parameters------------------//
		
		String str1 = "msg_threshold";
		String str2 = "msg_threshold2";
		//String str1 = "SubCategoryWeight_User";
		//String str2 = "SubCategoryWeight_Naver";
		
		Double parameter1[] = { 0.0 };
		Double parameter2[] = { 0.0,0.05,0.1,0.15,0.2,0.25,0.3 };
		
		//Double parameter1[] = { 0.0, 0.2, 0.4, 0.6, 0.8, 1.0 };
		//Double parameter2[] = { 0.0, 0.2, 0.4, 0.6, 0.8, 1.0 };
		//Double parameter2[] = { 0.0,0.05,0.1,0.15,0.2,0.25,0.3 };
		//Double parameter2[] = { 0.25 };
		
		//Double msg_threshold2[] = {0.0,0.05,0.1,0.15,0.2,0.25,0.3};
		//Double msg_threshold2[] = {0.0};
		total_exp_ct = parameter1.length * parameter2.length ;
		
		//-----------------------------------------------//
		sheet.setColumnView(1, 25);
		sheet2.setColumnView(1, 25);

		sheet.mergeCells(1, 1, 1 + total_exp_ct, 1);
		sheet2.mergeCells(1, 1, 1 + total_exp_ct, 1);
		
		Label label_title = new Label(1, 1, Exp.resultPathAppend, cellFormat);
		sheet.addCell(label_title);
		sheet2.addCell(label_title);

		Label label_th1 = new Label(1, 2, str1, cellFormat);
		sheet.addCell(label_th1);
		sheet2.addCell(label_th1);

		Label label_th2 = new Label(1, 3, str2, cellFormat);
		sheet.addCell(label_th2);
		sheet2.addCell(label_th2);
		
		for(Double th1 : parameter1){
			for(Double th2 : parameter2){
				exp_ct++;
				Label label_th1_value = new Label(1 + exp_ct, 2, th1.toString(), cellFormat);
				sheet.addCell(label_th1_value);
				sheet2.addCell(label_th1_value);
				
				Label label_th2_value = new Label(1 + exp_ct, 3, th2.toString(), cellFormat);
				sheet.addCell(label_th2_value);
				sheet2.addCell(label_th2_value);
				
				setParameters(str1, th1);
				setParameters(str2, th2);
				
				Exp.resultPathTestAppend = th1.toString() + " " + th2.toString();
				
				runExp();
			}
		}
		
		workbook.write();
		workbook.close();
		
		System.out.println("Complete"); 
	}
	public static void runExp() throws Exception{
		//--------------Initialize Main Class------------------//
		SNSLoader sloader = new SNSLoader(Exp.SNSType);
		MiningMindsEngine engine = new MiningMindsEngine(Exp.SNSType);
		Map<String, SNSUserBean> userMap = new HashMap<String, SNSUserBean>();
		//-----------------------------------------------------//

		userMap = sloader.getUserMap();
		int totalct = userMap.size();
		int ct = 0;
		for (Map.Entry<String, SNSUserBean> userMapEntry : userMap.entrySet()){
			ct++;
			String userID = userMapEntry.getKey();
			if(exp_ct == 1){
				Label label_ID = new Label(1, 4 + ct, userID, cellFormat);
				sheet.addCell(label_ID);
			}
			SNSUserBean userBean = userMapEntry.getValue();
			Map<String, Double> recomTotalCategoryMap;
			
			if(Exp.approach.contains("total")){
				recomTotalCategoryMap = engine.getCategoryList(userBean);
			}else{
				Map<String, SNSUserMsgBean> msgMap = userBean.getMsgMap();
				for (Map.Entry<String, SNSUserMsgBean> msgMapEntry : msgMap.entrySet()){
					SNSUserMsgBean userMsgBean = msgMapEntry.getValue();
					Map<String, Double> categoryMap = engine.getCategoryList(userMsgBean);
					userMsgBean.setRecomCategoryMap(categoryMap);
				}
				recomTotalCategoryMap = userBean.computeRecomTotalCategoryMap();
			}
			
			Map<String, Double> labelTotalCategoryMap = userBean.computeLabelTotalCategoryMap();
			
			double sim = engine.getCosineSimilarity(recomTotalCategoryMap, labelTotalCategoryMap);
			userBean.setSimilarity(sim);
			double acc = userBean.getMsgAccuracy();
			
			System.out.print("[EXP:"+exp_ct +"/"+ total_exp_ct+"] ");
			System.out.println("userid : " + userID + " , similarity : "+ String.format("%.4f", sim) + " , (" + ct + "/" + totalct +")");
			
			Label label_sim = new Label(1 + exp_ct, 4 + ct, String.format("%.4f", sim) , cellFormat);
			Label label_acc = new Label(1 + exp_ct, 4 + ct, String.format("%.4f", acc) , cellFormat);
			
			sheet.addCell(label_sim);
			sheet2.addCell(label_acc);
			
		}
		
		System.out.println("Generating Result...");
		if(!Exp.approach.contains("total")){
			sloader.generateResultHTML();
		}
		sloader.generateParameterFile();
		sloader.generateResultFile();
		sloader.generateRecomCategoryResultFile();
		sloader.generateMsgAccuracyResultFile();
		
		double averageSim = sloader.getAverageSimilarity();
		double averageAcc = sloader.getAverageMsgAccuracy();
		
		System.out.println("average similarity : "+ String.format("%.4f", averageSim));
		Label label_avr_sim = new Label(1 + exp_ct, 4 + ct + 2, String.format("%.4f", averageSim) , cellFormat);
		Label label_avr_acc = new Label(1 + exp_ct, 4 + ct + 2, String.format("%.4f", averageAcc) , cellFormat);
		
		sheet.addCell(label_avr_sim);
		sheet2.addCell(label_avr_acc);
		
	}
	
	public static void setParameters( String parameter, Double value  ) throws Exception{
		
		if(parameter.equals("msg_threshold")){
			Exp.msg_threshold = value;
		}else if(parameter.equals("msg_threshold2")){
			Exp.msg_threshold2 = value;
		}else if(parameter.equals("SubCategoryWeight_Naver")){
			Exp.subCategoryWeight_Naver = value;
		}else if(parameter.equals("SubCategoryWeight_User")){
			Exp.subCategoryWeight_User = value;
		}else if(parameter.equals("SubCategoryWeight")){
			Exp.subCategoryWeight_User = value;
			Exp.subCategoryWeight_Naver = value;
		}
		
		
	}

	
}
